#include "vl_c_dirty_support.h"
#include "vl_c_config_support.h"
#include "support/vl_valid_method.h"
#include "utils/vl_thread_pool.h"

using namespace VL;

namespace VL {

/**
 * @Author: CimZzz
 * @Date: 2022-08-12 11:17:37
 * 
 * C / C++ 文件验证码
 */
enum CValidCode {
	// 时间戳
	TS = 2,
	// 预处理参数
	PREPROCESS_FLAGS,
	// 头文件
	HEADER,
	// 源文件时间戳
	SOURCE_TS,
	// 目标文件时间戳
	TARGET_TS,
	// 编译参数
	COMPILE_FLAGS,
	// 链接参数
	LDFLAGS,
	// 编译器
	COMPILER,
	// 系统根
	SYSTEM_ROOT
};

/**
 * @Author: CimZzz
 * @Date: 2022-11-06 07:48:24
 * 
 * 获取文件校验码的检验不通过信息
 * 
 * @param code 校验码
 */
const char * getCValidCodeInvalidMessage(uint32_t code) {
	switch(code) {
		case CValidCode::TS :
		return "file is changed";
		case CValidCode::PREPROCESS_FLAGS :
		return "process flag is changed";
		case CValidCode::HEADER :
		return "header file is changed";
		case CValidCode::SOURCE_TS :
		return "source file is changed";
		case CValidCode::TARGET_TS :
		return "target file is changed";
		case CValidCode::COMPILE_FLAGS :
		return "compile flags is changed";
		case CValidCode::LDFLAGS :
		return "link flags is changed";
		case CValidCode::COMPILER :
		return "compiler is changed";
		case CValidCode::SYSTEM_ROOT :
		return "sysroot is changed";
	}
	return "unknown";
}

/**
 * @Author: CimZzz
 * @Date: 2022-11-06 08:21:36
 * 
 * 设置文件变化或者未变化, 包含详细信息打印
 * 
 * @param fileWrapper 文件包装器
 * @param isChanged 是否发生变化
 * @param isVerbose 是否输出详细信息
 * @param checkCode 文件校验码
 */
void setFileChanged(const std::shared_ptr<FileWrapper>& fileWrapper, bool isChanged, CommonConfigParams::VerboseType verboseType, uint32_t checkCode = 0) {
	bool isVerbose = (verboseType & CommonConfigParams::VerboseType::VT_Dirty) != 0;
	if(!isChanged) {
		fileWrapper->setFileChanged(false);
		if(isVerbose) {
			_VL_PRINT("%s not change", fileWrapper->getAbsolutePathStr());
		}
	} else {
		if(isVerbose) {
			_VL_PRINT_WARN("%s changed, because %s", fileWrapper->getAbsolutePathStr(), getCValidCodeInvalidMessage(checkCode));
			// 输出详细信息
			auto changeHook = [](FileWrapper* src, FileWrapper* effect) {
				_VL_PRINT_WARN("%s changed, cause by %s", effect->getAbsolutePathStr(), src->getAbsolutePathStr())
				return true;
			};
			fileWrapper->setFileChanged(true, changeHook);
		} else {
			fileWrapper->setFileChanged(true);
		}
	}
}

}


/**
 * @Author: CimZzz
 * @Date: 2022-08-21 00:02:55
 * 
 * 构造函数
 */
CDirtySupport::CDirtySupport(): VLSupport(VLSupport::Aspect::Dirty) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-19 15:53:54
 * 
 * 执行动作
 * 
 * @param env 环境变量
 */
void CDirtySupport::doAction(VLEnv* env) {
	// 加载 C / C++ 项目工程配置文件, 转换为内存中的数据类型
	this->initProjectMustExist(env);

	auto projectProp = env->projectProperties;
	auto dirtyParams = env->dirtyParams;

	// 检查 env 中是否已经存在对应的 Dirty 信息
	// 如果存在, 则直接跳过本次 Dirty 检查
	auto dirtyBundle = env->getVariable<CDirtyBundle>("C_DIRTY_BUNDLE");
	if(dirtyBundle.get() != nullptr) {
		// 跳过读取 Dirty 阶段, 直接到打印阶段
		if(dirtyParams->needPrint) {
			this->printConfig(dirtyBundle);
		}
		return;
	}
	dirtyBundle = std::shared_ptr<CDirtyBundle>(new CDirtyBundle());
	this->makeSureValidStreamExist(dirtyBundle);

	// 需要获取项目配置信息
	CConfigSupport configSupport;
	env->configureParams = std::shared_ptr<ConfigureParams>(new ConfigureParams);
	env->configureParams->configOptions = dirtyParams->dirtyOptions;
	env->configureParams->needPrint = false;
	configSupport.doAction(env);
	auto configBundle = env->getVariable<CConfigBundle>("C_CONFIG_BUNDLE");
	
	// 开始进行 Dirty Check
	
	// 初始化线程池
	env->initThreadPool();

	/**
	 * ****************************************************************************************
	 * @Author: CimZzz
	 * @Date: 2022-08-21 00:42:21
	 * 代码块说明: 
	 * 
	 * 针对项目源文件的 Dirty Check
	 * 
	 */
	
	auto sourceFileListPtr = configBundle->sourceFilePool->getFileList();
	if(!sourceFileListPtr->empty()) {
		dirtyBundle->targetFileCollectorPtr = std::shared_ptr<FileCollector>(new FileCollector);

		// 线程准备
		auto threadPoolPtr = VLThreadPool::getInstance();
		for(auto sourceIter = sourceFileListPtr->begin() ; sourceIter != sourceFileListPtr->end() ; sourceIter ++) {
			// 获取源文件指针
			auto sourceFilePtr = (*sourceIter);

			threadPoolPtr->exec([&, sourceFilePtr](Buffer* buffer) {
				std::vector<void*> paramList;
				int64_t modifyTime = sourceFilePtr->getModifyTime();
				paramList.push_back(&modifyTime);
				paramList.push_back(&configBundle->CPPFLAGS.flagStr);
				paramList.push_back(configBundle->headerFilePool.get());
				uint32_t checkCode = dirtyBundle->sourceValidStreamPtr->valid(sourceFilePtr->getValidFilePtr().get(), paramList);

				if(checkCode == 0) {
					// 文件未发生变化
					setFileChanged(sourceFilePtr, false, env->commonParams->verbose);
				} else {
					setFileChanged(sourceFilePtr, true, env->commonParams->verbose, checkCode);
					dirtyBundle->targetFileCollectorPtr->savePrimaryFile(sourceFilePtr->getFileKey(), sourceFilePtr);
				}
			});		
		}
		threadPoolPtr->waitForAllTaskDone();
		// 源文件检查完毕
	}
	
	/**
	 * ****************************************************************************************
	 * @Author: CimZzz
	 * @Date: 2022-08-21 17:31:37
	 * 代码块说明: 
	 * 
	 * 针对项目目标文件的 Dirty Check
	 * 
	 */

	// 项目目标文件
	auto targetFileListPtr = configBundle->targetFilePool->getFileList();
	if(!targetFileListPtr->empty()) {
		if(dirtyBundle->targetFileCollectorPtr.get() == nullptr) {
			dirtyBundle->targetFileCollectorPtr = std::shared_ptr<FileCollector>(new FileCollector);
		}

		// 线程准备
		auto threadPoolPtr = VLThreadPool::getInstance();
		for(auto targetIter = targetFileListPtr->begin() ; targetIter != targetFileListPtr->end() ; targetIter ++) {
			// 获取目标文件指针
			auto targetFilePtr = (*targetIter);
			if(targetFilePtr->isFileChange()) {
				// 由源文件推导已经发生变化
				dirtyBundle->targetFileCollectorPtr->saveRelateFile(targetFilePtr->getFileKey(), targetFilePtr);
				continue;
			}

			threadPoolPtr->exec([&, targetFilePtr](Buffer* buffer) {
				std::vector<void*> paramList;
				auto sourceFilePtr = targetFilePtr->getFirstDependentFile();
				int64_t sourceModifyTime = sourceFilePtr->getModifyTime();
				int64_t targetModifyTime = targetFilePtr->getModifyTime();
				paramList.push_back(&sourceModifyTime);
				paramList.push_back(&targetModifyTime);
				if(targetFilePtr->containFlag(CFileType::CFT_CPP)) {
					paramList.push_back(&configBundle->CXXFLAGS.flagStr);
					paramList.push_back(&configBundle->CXX);
				} else {
					paramList.push_back(&configBundle->CFLAGS.flagStr);
					paramList.push_back(&configBundle->CC);
				}
				paramList.push_back(&configBundle->CPPFLAGS.flagStr);
				paramList.push_back(&configBundle->SYSROOT);
				uint32_t checkCode = dirtyBundle->targetValidStreamPtr->valid(targetFilePtr->getValidFilePtr().get(), paramList);

				if(checkCode == 0) {
					// 文件未发生变化
					setFileChanged(targetFilePtr, false, env->commonParams->verbose);
				} else {
					setFileChanged(targetFilePtr, true, env->commonParams->verbose, checkCode);
					dirtyBundle->targetFileCollectorPtr->saveFile(sourceFilePtr->getFileKey(), sourceFilePtr, targetFilePtr);
				}
			});		
		}
		threadPoolPtr->waitForAllTaskDone();
		// 目标文件检查完毕
	}

	/**
	 * ****************************************************************************************
	 * @Author: CimZzz
	 * @Date: 2022-08-21 17:38:34
	 * 代码块说明: 
	 * 
	 * 针对项目位置无关目标文件的 Dirty Check
	 * 
	 */


	auto libTargetFileListPtr = configBundle->libTargetFilePool->getFileList();
	if(!libTargetFileListPtr->empty()) {
		if(dirtyBundle->targetFileCollectorPtr.get() == nullptr) {
			dirtyBundle->targetFileCollectorPtr = std::shared_ptr<FileCollector>(new FileCollector);
		}

		// 线程准备
		auto threadPoolPtr = VLThreadPool::getInstance();
		for(auto targetIter = libTargetFileListPtr->begin() ; targetIter != libTargetFileListPtr->end() ; targetIter ++) {
			// 获取目标文件指针
			auto targetFilePtr = (*targetIter);
			if(targetFilePtr->isFileChange()) {
				// 由源文件推导已经发生变化
				dirtyBundle->targetFileCollectorPtr->saveRelateFile(targetFilePtr->getFileKey(), targetFilePtr);
				continue;
			}

			auto futurePtr = threadPoolPtr->exec<bool, VLException>([&, targetFilePtr](const std::shared_ptr<VLFuture>& futurePtr, Buffer* buffer) {
				std::vector<void*> paramList;
				auto sourceFilePtr = targetFilePtr->getFirstDependentFile();
				int64_t sourceModifyTime = sourceFilePtr->getModifyTime();
				int64_t targetModifyTime = targetFilePtr->getModifyTime();
				paramList.push_back(&sourceModifyTime);
				paramList.push_back(&targetModifyTime);
				if(targetFilePtr->containFlag(CFileType::CFT_CPP)) {
					paramList.push_back(&configBundle->CXXFLAGS.flagStr);
					paramList.push_back(&configBundle->CXX);
				} else {
					paramList.push_back(&configBundle->CFLAGS.flagStr);
					paramList.push_back(&configBundle->CC);
				}
				paramList.push_back(&configBundle->CPPFLAGS.flagStr);
				paramList.push_back(&configBundle->SYSROOT);
				uint32_t checkCode = dirtyBundle->targetValidStreamPtr->valid(targetFilePtr->getValidFilePtr().get(), paramList);

				if(checkCode == 0) {
					// 文件未发生变化
					setFileChanged(targetFilePtr, false, env->commonParams->verbose);
				} else {
					setFileChanged(targetFilePtr, true, env->commonParams->verbose, checkCode);
					dirtyBundle->targetFileCollectorPtr->saveFile(sourceFilePtr->getFileKey(), sourceFilePtr, targetFilePtr);
				}
			});		
		}
		threadPoolPtr->waitForAllTaskDone();
		// 目标文件检查完毕
	}

	/**
	 * ****************************************************************************************
	 * @Author: CimZzz
	 * @Date: 2022-08-21 18:27:38
	 * 代码块说明: 
	 * 
	 * 针对项目测试用例文件的 Dirty Check
	 * 
	 */

	auto testBundlesPtr = configBundle->testBundlesPtr;
	if(testBundlesPtr.get() != nullptr) {
		// 组装测试用例源文件和目标文件验证流
		dirtyBundle->testTargetFileCollectorPtr = std::shared_ptr<FileCollector>(new FileCollector);


		for(auto bundlePtr = testBundlesPtr->begin() ; bundlePtr != testBundlesPtr->end() ; bundlePtr ++) {
			auto testBundlePtr = (*bundlePtr);
			if(testBundlePtr->dismissDep) {
				this->throwException("must call \"vl_build dep\" first to load dep");
			}
			auto testFilePtr = testBundlePtr->testFilePtr;
			auto testTargetFileListPtr = testBundlePtr->testFilePtr->getDependentFileList();

			auto threadPoolPtr = VLThreadPool::getInstance();
			for(auto targetIter = testTargetFileListPtr->begin() ; targetIter != testTargetFileListPtr->end() ; targetIter ++) {
				auto targetFilePtr = (*targetIter);
				if(targetFilePtr->containFlag(CFileType::CFT_STATIC)) {
					// 不针对静态库文件进行 Dirty Check
					continue;
				}
				auto sourceFilePtr = targetFilePtr->getFirstDependentFile();
				if(!sourceFilePtr->containFlag(CFileType::CFT_TEST)) {
					// 仅针对测试用例源文件进行 Dirty Check
					continue;
				}

				threadPoolPtr->exec([&, targetFilePtr, sourceFilePtr](Buffer* buffer) {
					// 源文件 Dirty Check
					std::vector<void*> paramList;
					int64_t sourceModifyTime, targetModifyTime;
					int64_t modifyTime = sourceFilePtr->getModifyTime();
					paramList.push_back(&modifyTime);
					paramList.push_back(&testBundlePtr->CPPFLAGS.flagStr);
					paramList.push_back(configBundle->headerFilePool.get());
					uint32_t checkCode = dirtyBundle->sourceValidStreamPtr->valid(sourceFilePtr->getValidFilePtr().get(), paramList);
					if(checkCode == 0) {
						// 文件未发生变化
						setFileChanged(sourceFilePtr, false, env->commonParams->verbose);
					} else {
						setFileChanged(sourceFilePtr, true, env->commonParams->verbose, checkCode);
						dirtyBundle->testTargetFileCollectorPtr->saveFile(sourceFilePtr->getFileKey(), sourceFilePtr, targetFilePtr);
						return;
					}

					// 目标文件 Dirty Check
					paramList.clear();
					sourceModifyTime = sourceFilePtr->getModifyTime();
					targetModifyTime = targetFilePtr->getModifyTime();
					paramList.push_back(&sourceModifyTime);
					paramList.push_back(&targetModifyTime);
					paramList.push_back(&testBundlePtr->COMPILE_FLAGS.flagStr);
					if(targetFilePtr->containFlag(CFileType::CFT_CPP)) {
						paramList.push_back(&configBundle->CXX);
					} else {
						paramList.push_back(&configBundle->CC);
					}
					paramList.push_back(&testBundlePtr->CPPFLAGS.flagStr);
					paramList.push_back(&configBundle->SYSROOT);
					checkCode = dirtyBundle->targetValidStreamPtr->valid(targetFilePtr->getValidFilePtr().get(), paramList);
					if(checkCode == 0) {
						// 文件未发生变化
						setFileChanged(targetFilePtr, false, env->commonParams->verbose);
					} else {
						setFileChanged(targetFilePtr, true, env->commonParams->verbose, checkCode);
						dirtyBundle->testTargetFileCollectorPtr->saveFile(sourceFilePtr->getFileKey(), sourceFilePtr, targetFilePtr);
						return;
					}
				});	
			}
			threadPoolPtr->waitForAllTaskDone();

			uint32_t checkCode;
			std::vector<void*> paramList;
			int64_t modifyTime = testFilePtr->getModifyTime();

			if(testFilePtr->isFileChange()) {
				// 目标文件发生改变, 不进行后续测试用例的 Dirty Check
				goto IS_TEST_DIRTY;
			}

			// 对测试用例文件进行 Dirty Check
			paramList.push_back(&testBundlePtr->LDFLAGS.flagStr);
			paramList.push_back(&modifyTime);
			paramList.push_back(testTargetFileListPtr.get());

			checkCode = dirtyBundle->execStreamPtr->valid(testFilePtr->getValidFilePtr().get(), paramList);
			if(checkCode == 0) {
				// 文件未发生变化
				setFileChanged(testFilePtr, false, env->commonParams->verbose);
			} else {
				setFileChanged(testFilePtr, true, env->commonParams->verbose, checkCode);
				goto IS_TEST_DIRTY;
			}

			// 未发生变化

			continue;

			IS_TEST_DIRTY:

			if(dirtyBundle->testBundlesPtr.get() == nullptr) {
				dirtyBundle->testBundlesPtr = std::shared_ptr<std::vector<std::shared_ptr<CTestBundle>>>(new std::vector<std::shared_ptr<CTestBundle>>);
			}

			dirtyBundle->testBundlesPtr->push_back(testBundlePtr);
		}
	}

	/**
	 * ****************************************************************************************
	 * @Author: CimZzz
	 * @Date: 2022-08-22 00:20:47
	 * 代码块说明: 
	 * 
	 * 针对项目可执行文件的 Dirty Check
	 * 
	 */

	auto execBundlesPtr = configBundle->execBundlesPtr;
	if(execBundlesPtr.get() != nullptr) {
		for(auto bundleIter = execBundlesPtr->begin() ; bundleIter != execBundlesPtr->end() ; bundleIter ++) {
			auto execBundlePtr = (*bundleIter);
			if(execBundlePtr->dismissDep) {
				this->throwException("must call \"vl_build dep\" first to load dep");
			}

			auto executableFilePtr = execBundlePtr->executableFilePtr;
			if(!execBundlePtr->executableFilePtr->isFileChange()) {
				// 对可执行文件进行 Dirty Check
				std::vector<void*> paramList;
				int64_t modifyTime = executableFilePtr->getModifyTime();

				// 对测试用例文件进行 Dirty Check
				paramList.push_back(&execBundlePtr->LDFLAGS.flagStr);
				paramList.push_back(&modifyTime);
				paramList.push_back(executableFilePtr->getDependentFileList().get());

				auto checkCode = dirtyBundle->execStreamPtr->valid(executableFilePtr->getValidFilePtr().get(), paramList);

				if(checkCode == 0) {
					// 文件未发生变化
					setFileChanged(executableFilePtr, false, env->commonParams->verbose);
				} else {
					setFileChanged(executableFilePtr, true, env->commonParams->verbose, checkCode);
				}
			}

			if(executableFilePtr->isFileChange()) {
				if(dirtyBundle->execBundlesPtr.get() == nullptr) {
					dirtyBundle->execBundlesPtr = std::shared_ptr<std::vector<std::shared_ptr<CExecutableBundle>>>(new std::vector<std::shared_ptr<CExecutableBundle>>);
				}

				dirtyBundle->execBundlesPtr->push_back(execBundlePtr);
			}
		}
	}

	/**
	 * ****************************************************************************************
	 * @Author: CimZzz
	 * @Date: 2022-08-22 08:14:50
	 * 代码块说明: 
	 * 
	 * 针对项目库文件的 Dirty Check
	 * 
	 */

	auto libBundlesPtr = configBundle->libBundlesPtr;
	if(libBundlesPtr.get() != nullptr) {
		for(auto bundleIter = libBundlesPtr->begin() ; bundleIter != libBundlesPtr->end() ; bundleIter ++) {

			auto libBundlePtr = (*bundleIter);
			if(libBundlePtr->dismissDep) {
				this->throwException("must call \"vl_build dep\" first to load dep");
			}
			bool isChanged = false;
			
			// 检查静态库文件
			auto staticFilePtr = libBundlePtr->staticFilePtr;
			if(staticFilePtr.get() != nullptr) {
				if(!staticFilePtr->isFileChange()) {
					// 对静态库文件进行 Dirty Check
					std::vector<void*> paramList;
					int64_t modifyTime = staticFilePtr->getModifyTime();

					paramList.push_back(&modifyTime);
					paramList.push_back(staticFilePtr->getDependentFileList().get());
					auto checkCode = dirtyBundle->staticStreamPtr->valid(staticFilePtr->getValidFilePtr().get(), paramList);

					if(checkCode == 0) {
						// 文件未发生变化
						setFileChanged(staticFilePtr, false, env->commonParams->verbose);
					} else {
						setFileChanged(staticFilePtr, true, env->commonParams->verbose, checkCode);
						isChanged = true;
					}
				} else {
					isChanged = true;
				}
			}
			
			// 检查位置无关静态库文件
			auto nopStaticFilePtr = libBundlePtr->nopStaticFilePtr;
			if(nopStaticFilePtr.get() != nullptr) {
				if(!nopStaticFilePtr->isFileChange()) {
					// 对静态库文件进行 Dirty Check
					std::vector<void*> paramList;
					int64_t modifyTime = nopStaticFilePtr->getModifyTime();

					paramList.push_back(&modifyTime);
					paramList.push_back(nopStaticFilePtr->getDependentFileList().get());
					auto checkCode = dirtyBundle->staticStreamPtr->valid(nopStaticFilePtr->getValidFilePtr().get(), paramList);

					if(checkCode == 0) {
						// 文件未发生变化
						setFileChanged(nopStaticFilePtr, false, env->commonParams->verbose);
					} else {
						setFileChanged(nopStaticFilePtr, true, env->commonParams->verbose, checkCode);
						isChanged = true;
					}
				} else {
					isChanged = true;
				}
			}

			// 检查动态库文件
			auto dynamicFilePtr = libBundlePtr->dynamicFilePtr;
			if(dynamicFilePtr.get() != nullptr) {
				if(!dynamicFilePtr->isFileChange()) {
					// 对动态库文件进行 Dirty Check
					std::vector<void*> paramList;
					int64_t modifyTime = dynamicFilePtr->getModifyTime();

					paramList.push_back(&libBundlePtr->LDFLAGS.flagStr);
					paramList.push_back(&modifyTime);
					paramList.push_back(dynamicFilePtr->getDependentFileList().get());
					auto checkCode = dirtyBundle->dynamicStreamPtr->valid(dynamicFilePtr->getValidFilePtr().get(), paramList);

					if(checkCode == 0) {
						// 文件未发生变化
						setFileChanged(dynamicFilePtr, false, env->commonParams->verbose);
					} else {
						setFileChanged(dynamicFilePtr, true, env->commonParams->verbose, checkCode);
						isChanged = true;
					}
				} else {
					isChanged = true;
				}
			}

			// 检查库头文件列表
			FileWrapperWalker walker(&libBundlePtr->headerFileListPtr);
			std::vector<void*> paramList;
			paramList.push_back(&walker);
			auto checkCode = dirtyBundle->headerStreamPtr->valid(libBundlePtr->libraryTsFile, paramList);
			if(checkCode != 0) {
				// 头文件发生变化, 组装到 LibraryBundle 中
				if(walker.getGroupCount() != 2) {
					// TS 文件读取失败
					libBundlePtr->needCopyFileListPtr = std::shared_ptr<std::vector<std::shared_ptr<FileWrapper>>>(new std::vector<std::shared_ptr<FileWrapper>>(libBundlePtr->headerFileListPtr));
					if(env->commonParams->verbose) {
						// 打印详细信息
						for(auto headerIter = libBundlePtr->headerFileListPtr.begin() ; headerIter != libBundlePtr->headerFileListPtr.end() ; headerIter ++) {
							_VL_PRINT_WARN("%s changed", (*headerIter)->getAbsolutePathStr())
						}
					}
				} else {
					auto needCopyFileListPtr = walker.getGroupPtr(0);
					auto needRemoveFileListPtr = walker.getGroupPtr(1);
					if(needCopyFileListPtr.get() != nullptr && !needCopyFileListPtr->empty()) {
						libBundlePtr->needCopyFileListPtr = needCopyFileListPtr;
					}
					if(needRemoveFileListPtr.get() != nullptr && !needRemoveFileListPtr->empty()) {
						libBundlePtr->needRemoveFileListPtr = needRemoveFileListPtr;
					}

					if(env->commonParams->verbose) {
						// 打印详细信息
						for(auto headerIter = needCopyFileListPtr->begin() ; headerIter != needCopyFileListPtr->end() ; headerIter ++) {
							_VL_PRINT_WARN("%s changed", (*headerIter)->getAbsolutePathStr())
						}
						for(auto headerIter = needRemoveFileListPtr->begin() ; headerIter != needRemoveFileListPtr->end() ; headerIter ++) {
							_VL_PRINT_IMPORTANT("%s need remove", (*headerIter)->getAbsolutePathStr())
						}
					}
				}
				isChanged = true;
			} else {
				if(env->commonParams->verbose) {
					// 打印详细信息
					for(auto headerIter = libBundlePtr->headerFileListPtr.begin() ; headerIter != libBundlePtr->headerFileListPtr.end() ; headerIter ++) {
						_VL_PRINT("%s not change", (*headerIter)->getAbsolutePathStr())
					}
				}
			}

			if(isChanged) {
				if(dirtyBundle->libBundlesPtr.get() == nullptr) {
					dirtyBundle->libBundlesPtr = std::shared_ptr<std::vector<std::shared_ptr<CLibraryBundle>>>(new std::vector<std::shared_ptr<CLibraryBundle>>);
				}

				dirtyBundle->libBundlesPtr->push_back(libBundlePtr);
			}
		}
	}

	// 变量重检
	if(dirtyBundle->targetFileCollectorPtr.get() != nullptr && dirtyBundle->targetFileCollectorPtr->empty()) {
		dirtyBundle->targetFileCollectorPtr.reset();
	}
	if(dirtyBundle->testTargetFileCollectorPtr.get() != nullptr && dirtyBundle->testTargetFileCollectorPtr->empty()) {
		dirtyBundle->testTargetFileCollectorPtr.reset();
	}
	if(dirtyBundle->execBundlesPtr.get() != nullptr && dirtyBundle->execBundlesPtr->empty()) {
		dirtyBundle->execBundlesPtr.reset();
	}
	if(dirtyBundle->libBundlesPtr.get() != nullptr && dirtyBundle->libBundlesPtr->empty()) {
		dirtyBundle->libBundlesPtr.reset();
	}
	if(dirtyBundle->testBundlesPtr.get() != nullptr && dirtyBundle->testBundlesPtr->empty()) {
		dirtyBundle->testBundlesPtr.reset();
	}

	// 至此, 全部 Dirty Check 完毕
	// 将 Dirty Check 更新至环境变量中
	env->saveVariable("C_DIRTY_BUNDLE", dirtyBundle);
	
	if(dirtyParams->needPrint) {
		this->printConfig(dirtyBundle);
	}
}


/**
 * @Author: CimZzz
 * @Date: 2022-08-21 00:51:25
 * 
 * 打印 Dirty 信息
 * 
 * @param bundle Dirty 参数集合
 */
void CDirtySupport::printConfig(const std::shared_ptr<CDirtyBundle>& bundle) {
	// 打印 DirtyCheck 相关信息
	printf("=============== Dirty Info ===============\n");
	auto targetFileCollectorPtr = bundle->targetFileCollectorPtr;
	if(targetFileCollectorPtr.get() != nullptr) {
		// 存在项目目标文件
		printf("Target file in project: \n");
		for(auto iter = targetFileCollectorPtr->begin() ; iter != targetFileCollectorPtr->end() ; iter ++) {
			auto pairPtr = iter->second;
			auto primaryFilePtr = pairPtr->primaryFile;
			auto relativeFileListPtr = pairPtr->relateFile;
			if(primaryFilePtr->isFileChange()) {
				printf("\033[31mX %s\033[0m\n", primaryFilePtr->getAbsolutePathStr());
			} else {
				printf("\033[32m√ %s\033[0m\n", primaryFilePtr->getAbsolutePathStr());
			}
			for(auto targetIter = relativeFileListPtr->begin() ; targetIter != relativeFileListPtr->end() ; targetIter ++) {
				auto targetFilePtr = (*targetIter);
				if(targetFilePtr->isFileChange()) {
					printf("- \033[31mX %s\033[0m\n", targetFilePtr->getAbsolutePathStr());
				} else {
					printf("- \033[32m√ %s\033[0m\n", targetFilePtr->getAbsolutePathStr());
				}
			}
		}
		printf("\n");
	}

	auto testTargetFileCollectorPtr = bundle->testTargetFileCollectorPtr;
	if(testTargetFileCollectorPtr.get() != nullptr) {
		// 存在测试项目目标文件
		printf("Test Target file in project: \n");
		for(auto iter = testTargetFileCollectorPtr->begin() ; iter != testTargetFileCollectorPtr->end() ; iter ++) {
			auto pairPtr = iter->second;
			auto primaryFilePtr = pairPtr->primaryFile;
			auto relativeFileListPtr = pairPtr->relateFile;
			if(primaryFilePtr->isFileChange()) {
				printf("\033[31mX %s\033[0m\n", primaryFilePtr->getAbsolutePathStr());
			} else {
				printf("\033[32m√ %s\033[0m\n", primaryFilePtr->getAbsolutePathStr());
			}
			for(auto targetIter = relativeFileListPtr->begin() ; targetIter != relativeFileListPtr->end() ; targetIter ++) {
				auto targetFilePtr = (*targetIter);
				if(targetFilePtr->isFileChange()) {
					printf("- \033[31mX %s\033[0m\n", targetFilePtr->getAbsolutePathStr());
				} else {
					printf("- \033[32m√ %s\033[0m\n", targetFilePtr->getAbsolutePathStr());
				}
			}
		}
		printf("\n");
	}

	auto testBundlesPtr = bundle->testBundlesPtr;
	if(testBundlesPtr.get() != nullptr) {
		// 存在测试项目
		printf("Test Units: \n");
		for(auto iter = testBundlesPtr->begin() ; iter != testBundlesPtr->end(); iter ++) {
			auto bundlePtr = (*iter);
			printf("-----\n");
			printf("%-18s: %s\n", "NAME", bundlePtr->name.c_str());
			printf("%-18s: \033[31m%s\033[0m\n", "PRODUCT", bundlePtr->testFilePtr->getAbsolutePathStr());
		}
		printf("\n");
	}

	auto execBundlesPtr = bundle->execBundlesPtr;
	if(execBundlesPtr.get() != nullptr) {
		// 存在可执行项目
		printf("Exectuables: \n");
		for(auto iter = execBundlesPtr->begin() ; iter != execBundlesPtr->end(); iter ++) {
			auto bundlePtr = (*iter);
			printf("-----\n");
			printf("%-18s: %s\n", "NAME", bundlePtr->name.c_str());
			printf("%-18s: \033[31m%s\033[0m\n", "PRODUCT", bundlePtr->executableFilePtr->getAbsolutePathStr());
		}
		printf("\n");
	}

	auto libBundlesPtr = bundle->libBundlesPtr;
	if(libBundlesPtr.get() != nullptr) {
		// 存在可执行项目
		printf("Libraries: \n");
		for(auto iter = libBundlesPtr->begin() ; iter != libBundlesPtr->end(); iter ++) {
			auto bundlePtr = (*iter);
			printf("-----\n");
			printf("%-18s: %s\n", "NAME", bundlePtr->name.c_str());
			if(bundlePtr->dynamicFilePtr.get() != nullptr && bundlePtr->dynamicFilePtr->isFileChange()) {
				printf("%-18s: \033[31m%s\033[0m\n", "DYNAMIC", bundlePtr->dynamicFilePtr->getAbsolutePathStr());
			}
			if(bundlePtr->staticFilePtr.get() != nullptr && bundlePtr->staticFilePtr->isFileChange()) {
				printf("%-18s: \033[31m%s\033[0m\n", "STATIC", bundlePtr->staticFilePtr->getAbsolutePathStr());
			}
			if(bundlePtr->nopStaticFilePtr.get() != nullptr && bundlePtr->nopStaticFilePtr->isFileChange()) {
				printf("%-18s: \033[31m%s\033[0m\n", "NOP STATIC", bundlePtr->nopStaticFilePtr->getAbsolutePathStr());
			}
			auto needCopyFileListPtr = bundlePtr->needCopyFileListPtr;
			auto needRemoveFileListPtr = bundlePtr->needRemoveFileListPtr;
			if(needCopyFileListPtr.get() != nullptr || needRemoveFileListPtr.get() != nullptr) {
				printf("%-18s: \n", "HEADERS");
				if(needCopyFileListPtr.get() != nullptr) {
					for(auto targetIter = needCopyFileListPtr->begin() ; targetIter != needCopyFileListPtr->end() ; targetIter ++) {
						auto targetFilePtr = (*targetIter);
						printf("\033[32m+ %s\033[0m\n", targetFilePtr->getAbsolutePathStr());
					}
				}
				if(needRemoveFileListPtr.get() != nullptr) {
					for(auto targetIter = needRemoveFileListPtr->begin() ; targetIter != needRemoveFileListPtr->end() ; targetIter ++) {
						auto targetFilePtr = (*targetIter);
						printf("\033[31m- %s\033[0m\n", targetFilePtr->getAbsolutePathStr());
					}
				}
			}
		}
		printf("\n");
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-22 00:21:50
 * 
 * 确保 Dirty 验证流存在
 * 
 * @param dirtyBundle Dirty 参数集合
 */
void CDirtySupport::makeSureValidStreamExist(std::shared_ptr<CDirtyBundle>& dirtyBundle) {
	// 组装源文件验证流
	// 源文件验证的属性包含
	// s: 源文件时间戳
	// p: CPPFLAGS
	// h: 头文件时间戳列表
	// 		[header name]: 头文件时间戳
	dirtyBundle->sourceValidStreamPtr = std::shared_ptr<ValidStream>(new ValidStream);
	dirtyBundle->sourceValidStreamPtr->addValidItem(new ValidItem<int64_t>(
		SOURCE_TS, "s", ValidCommonMethod::validTsFunc, ValidCommonMethod::overrideTsFunc
	));
	dirtyBundle->sourceValidStreamPtr->addValidItem(new ValidItem<std::string>(
		PREPROCESS_FLAGS, "p", ValidCommonMethod::validStrFunc, ValidCommonMethod::overrideStrFunc
	));
	dirtyBundle->sourceValidStreamPtr->addValidItem(new CustomValidItem<FilePool, std::vector<std::shared_ptr<FileWrapper>>>(
		HEADER, "h", 
		ValidCommonMethod::validFilePoolFunc,
		ValidCommonMethod::overrideFileListWithFullPathFunc
	));

	// 组装目标文件验证流
	// 目标文件验证的属性包含
	// s: 源文件时间戳
	// t: 目标文件时间戳
	// cf: CFLAGS / CXXFLAGS
	// c: CXX / CC
	// p: CPPFLAGS
	// sys: SYSROOT
	dirtyBundle->targetValidStreamPtr = std::shared_ptr<ValidStream>(new ValidStream);
	dirtyBundle->targetValidStreamPtr->addValidItem(new ValidItem<int64_t>(
		SOURCE_TS, "s", ValidCommonMethod::validTsFunc, ValidCommonMethod::overrideTsFunc
	));
	dirtyBundle->targetValidStreamPtr->addValidItem(new ValidItem<int64_t>(
		TARGET_TS, "t", ValidCommonMethod::validTsFunc, ValidCommonMethod::overrideTsFunc
	));
	dirtyBundle->targetValidStreamPtr->addValidItem(new ValidItem<std::string>(
		COMPILE_FLAGS, "cf", ValidCommonMethod::validStrFunc, ValidCommonMethod::overrideStrFunc
	));
	dirtyBundle->targetValidStreamPtr->addValidItem(new ValidItem<std::string>(
		COMPILER, "c", ValidCommonMethod::validStrFunc, ValidCommonMethod::overrideStrFunc
	));
	dirtyBundle->targetValidStreamPtr->addValidItem(new ValidItem<std::string>(
		PREPROCESS_FLAGS, "p", ValidCommonMethod::validStrFunc, ValidCommonMethod::overrideStrFunc
	));
	dirtyBundle->targetValidStreamPtr->addValidItem(new ValidItem<std::string>(
		SYSTEM_ROOT, "sys", ValidCommonMethod::validStrFunc, ValidCommonMethod::overrideStrFunc
	));

	// 组装可执行文件验证流
	// 可执行文件验证的属性包含
	// ldf: LDFLAGS
	// p: 可执行时间戳
	// t: 目标文件时间戳 Map
	// 		[target name]: 目标文件时间戳
	// 		[target name]: 目标文件时间戳
	dirtyBundle->execStreamPtr = std::shared_ptr<ValidStream>(new ValidStream);
	dirtyBundle->execStreamPtr->addValidItem(new ValidItem<std::string>(
		LDFLAGS, "ldf", ValidCommonMethod::validStrFunc, ValidCommonMethod::overrideStrFunc
	));
	dirtyBundle->execStreamPtr->addValidItem(new ValidItem<int64_t>(
		TS, "p", ValidCommonMethod::validTsFunc, ValidCommonMethod::overrideTsFunc
	));
	dirtyBundle->execStreamPtr->addValidItem(new ValidItem<std::vector<std::shared_ptr<FileWrapper>>>(
		TARGET_TS, "t",
		ValidCommonMethod::validFileListWithFullPathFunc,
		ValidCommonMethod::overrideFileListWithFullPathFunc
	));

	// 组装动态库验证流
	// 动态库验证的属性包含
	// ldf: LDFLAGS
	// l: 库文件时间戳
	// t: 目标文件时间戳 Map
	// 		[target name]: 目标文件时间戳
	// 		[target name]: 目标文件时间戳
	dirtyBundle->dynamicStreamPtr = std::shared_ptr<ValidStream>(new ValidStream);
	dirtyBundle->dynamicStreamPtr->addValidItem(new ValidItem<std::string>(
		LDFLAGS, "ldf", ValidCommonMethod::validStrFunc, ValidCommonMethod::overrideStrFunc
	));
	dirtyBundle->dynamicStreamPtr->addValidItem(new ValidItem<int64_t>(
		TS, "l", ValidCommonMethod::validTsFunc, ValidCommonMethod::overrideTsFunc
	));
	dirtyBundle->dynamicStreamPtr->addValidItem(new ValidItem<std::vector<std::shared_ptr<FileWrapper>>>(
		TARGET_TS, "t",
		ValidCommonMethod::validFileListWithFullPathFunc,
		ValidCommonMethod::overrideFileListWithFullPathFunc
	));

	// 组装静态库验证流
	// 静态库验证的属性包含
	// l: 库文件时间戳
	// t: 目标文件时间戳 Map
	// 		[target name]: 目标文件时间戳
	// 		[target name]: 目标文件时间戳
	dirtyBundle->staticStreamPtr = std::shared_ptr<ValidStream>(new ValidStream);
	dirtyBundle->staticStreamPtr->addValidItem(new ValidItem<int64_t>(
		TS, "l", ValidCommonMethod::validTsFunc, ValidCommonMethod::overrideTsFunc
	));
	dirtyBundle->staticStreamPtr->addValidItem(new ValidItem<std::vector<std::shared_ptr<FileWrapper>>>(
		TARGET_TS, "t",
		ValidCommonMethod::validFileListWithFullPathFunc,
		ValidCommonMethod::overrideFileListWithFullPathFunc
	));

	// 组装头文件验证流
	// 头文件验证的属性包含
	// h: 头文件文件时间戳 Map
	// 		[header name]: 头文件时间戳
	// 		[header name]: 头文件时间戳
	dirtyBundle->headerStreamPtr = std::shared_ptr<ValidStream>(new ValidStream);
	dirtyBundle->headerStreamPtr->addValidItem(new CustomValidItem<FileWrapperWalker, std::vector<std::shared_ptr<FileWrapper>>>{
		HEADER, "h",
		ValidCommonMethod::validFileListWithFullPathAndCollectDepFirstFunc,
		ValidCommonMethod::overrideFileListDepFirstFunc
	});
}